//
//  PerformSelectorTest.m
//  Charles
//
//  Created by Charles on 2018/6/5.
//  Copyright © 2018年 charles. All rights reserved.
//

#import "PerformSelectorTest.h"

@implementation PerformSelectorTest

/**
 不传递调用
 */
- (void)testPerformSelector {
    [self performSelector:@selector(testMethod)];
}

- (void)testMethod {
    NSLog(@"testPerfomSelctor no argument!");
}

/**
 传递一个参数
 */
- (void)testPerformSelectorWithOneArgument{
    [self performSelector:@selector(testMethodArgment:) withObject:@"first argument"];
}

- (void)testMethodArgment:(NSString *)firstArg {
    NSLog(@"argument is %@",firstArg);
}

/**
 传递两个参数
 */
- (void)testPerformSelectorWithTwoArgument {
    [self performSelector:@selector(testMethodArgment:secondArg:) withObject:@"first argument" withObject:@"second argument"];
}

- (void)testMethodArgment:(NSString *)firstArg secondArg:(NSString *)secondArg{
    NSLog(@"argument is %@ %@",firstArg,secondArg);
}

- (void)testPerformSelectorWithDynamicFunction{
    NSArray *functions = @[@{@"methodName":@"dynamicArgString:",@"value":@"String"},@{@"methodName":@"dynamicArgNumber:",@"value":@2}];
    for (NSDictionary *function in functions) {
        SEL method = NSSelectorFromString([function objectForKey:@"methodName"]);
        id argument = [function objectForKey:@"value"];
        [self performSelector:method withObject:argument afterDelay:0];
    }
}

- (void)dynamicArgString:(NSString *)argString {
    NSLog(@"dynamicArgString : %@",argString);
}

- (void)dynamicArgNumber:(NSNumber *)argNumber {
    NSLog(@"dynamicArgNumber : %@",argNumber);
}

- (void)testSubThreadInvokePerfromSelector {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        /* 系统实现
         - (id)performSelector:(SEL)sel {
            if (!sel) [self doesNotRecognizeSelector:sel];
                return ((id(*)(id, SEL))objc_msgSend)(self, sel);
         }
         */
        [self performSelector:@selector(testOne) withObject:nil];
        /* 系统实现
         - (void) performSelector: (SEL)aSelector
         withObject: (id)argument
         afterDelay: (NSTimeInterval)seconds{
            NSRunLoop        *loop = [NSRunLoop currentRunLoop];
            GSTimedPerformer    *item;
         
            item = [[GSTimedPerformer alloc] initWithSelector: aSelector
                target: self
                argument: argument
                delay: seconds];
            [[loop _timedPerformers] addObject: item];
            RELEASE(item);
            [loop addTimer: item->timer forMode: NSDefaultRunLoopMode];
         }
         */
        [self performSelector:@selector(testTwo) withObject:nil afterDelay:0];
        // runloop的开启操作，必须放在事件调用的后面，因为如果runloop中没有任何timer/source/observer的话，
        // 是开启不了的。
        NSRunLoop *runloop = [NSRunLoop currentRunLoop];
        [runloop run];
    });
}

- (void)testOne {
    NSLog(@"Test One");
}

- (void)testTwo {
    NSLog(@"Test Two");
}

@end
